home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / human interface toolbox / concordia / drawtkl.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  17.2 KB  |  476 lines

  1. /*
  2.     File:        DrawTkl.c
  3.  
  4.     Contains:    the code to process the mDrawMsg message from the Menu
  5.                 Manager.  This source file contains the routines to do ALL drawing, including
  6.                 the scroll icons.
  7.  
  8.     Written by:     
  9.  
  10.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  11.  
  12.                 You may incorporate this Apple sample source code into your program(s) without
  13.                 restriction. This Apple sample source code has been provided "AS IS" and the
  14.                 responsibility for its operation is yours. You are not permitted to redistribute
  15.                 this Apple sample source code as "Apple sample source code" after having made
  16.                 changes. If you're going to re-distribute the source, we require that you make
  17.                 it clear in the source that the code was descended from Apple sample source
  18.                 code, but that you've made changes.
  19.  
  20.     Change History (most recent first):
  21.                 8/10/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  22.                 
  23.  
  24. */
  25.  
  26.  
  27. /******************************************************************************\
  28. * Header Files
  29. \******************************************************************************/
  30.  
  31. #include <Memory.h>
  32. #include <Menus.h>
  33. #include <Resources.h>
  34. #include <ToolUtils.h>
  35. #include <Icons.h>
  36. #include <Types.h>
  37. #include "Concordia.h"
  38. #include "DrawTkl.h"
  39. #include "SizeTkl.h"
  40.  
  41.  
  42. /******************************************************************************\
  43. * Constants & Macros
  44. \******************************************************************************/
  45.  
  46. #define scrlSICNID -12288 //Resource ID of scroll arrows SICN
  47.  
  48.  
  49. /******************************************************************************\
  50. * Type Declarations
  51. \******************************************************************************/
  52.  
  53. /* Small icon data */
  54. typedef Byte SICNData [32];
  55.  
  56.  
  57. /******************************************************************************\
  58. * Function Prototypes
  59. \******************************************************************************/
  60.  
  61. void DimRect (Rect *);
  62. void DrawSICN (SICNData **, short, short, short);
  63. void DrawICON (Handle, Rect *);
  64.  
  65.  
  66. #pragma segment Main
  67. /******************************************************************************\
  68. * DoDrawMsg - Draw a menu
  69. *
  70. * DoDrawMsg draws the menu specified by TheMenu.  The rectangle in global coord-
  71. * inates that the menu occupies is specified in MenuRect.  If the system global
  72. * TopMenuItem is not equal to the top coordinate of MenuRect, a top scroll bar
  73. * is drawn.  If the menu extends below the bottom of MenuRect, a bottom scroll
  74. * bar is drawn.  The Menu Manager (I guess) sets TopMenuItem properly for pull-
  75. * down menus, while the popup menu tackler (DoPopupMsg) sets TopMenuItem
  76. * properly for popup menus.  DoDrawMsg sets the system global AtMenuBottom to
  77. * the bottom of the entire menu, regardless of whether it fits on the screen or
  78. * not.
  79. *
  80. * Coding Notes
  81. * #A# - The sole purpose of this loop is to find the total height of the menu in 
  82. *       pixels ignoring the size of the screen.  Seems like kind of a waste,
  83. *       doesn't it?
  84. * #B# - The clip rectangle, MenuClip is only set if the menu has scroll icons.
  85. *       This is determined here.
  86. * #C# - This loop draws each of the menu items.
  87. * #D# - Side-effect: system global AtMenuBottom set to coordinate of bottom of
  88. *       Menu regardless of whether the menu fits or not.
  89. * #E# - We don’t need the menuEnabled bit any more so get rid of it by shifting
  90. *       it out.  Then we have to set the high bit so that all items beyond the
  91. *       31st will be enabled.  With arithmetic right shifting, this high bit
  92. *       will be preserved.
  93. \******************************************************************************/
  94.  
  95. void
  96. DoDrawMsg (TheMenu, MenuRect)
  97.     MenuHandle TheMenu;   //=> Menu to draw >>
  98.     Rect       *MenuRect; //-> Menu's rectangle in global coords >>
  99.     {
  100.     Str255      *ItemString; //-> Menu item's string
  101.     ItemInfoPtr ItemInfo;    //-> Item info
  102.     Rect        ItemRect;    //Item's rectangle
  103.     Rect        TotMenuRect; //Menu's rectangle w/o clipping to screen
  104.     RgnHandle   SaveClip;    //=> Saved clip region
  105.     Rect        MenuClip;    //Clip region of menu if menu scrolls
  106.     long        EnableFlags; //Menu's enable flags
  107.  
  108.     SaveClip = (RgnHandle) null;
  109.     if ((**TheMenu).enableFlags & 1)
  110.         {
  111.         EnableFlags = (unsigned long) (**TheMenu).enableFlags >> 1; //#E#
  112.         EnableFlags |= 0x80000000;
  113.         }
  114.     else
  115.         EnableFlags = 0;
  116.     SetRect (&TotMenuRect, MenuRect->left, sgTopMenuItem, MenuRect->right,
  117.             sgTopMenuItem);
  118.     HLock ((Handle) TheMenu);
  119.     ItemString = (Str255 *) (**TheMenu).menuData;
  120.     ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
  121.     while ((*ItemString) [0] != (char) 0) //#A#
  122.         {
  123.         ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
  124.         TotMenuRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
  125.         ItemString = (Str255 *) (ItemInfo + 1);
  126.         }
  127.     HUnlock ((Handle) TheMenu);
  128.     MenuClip = *MenuRect;
  129.     if (TotMenuRect.top != MenuRect->top || TotMenuRect.bottom != MenuRect->
  130.             bottom) //#B#
  131.         {
  132.         if (TotMenuRect.top != MenuRect->top)
  133.             {
  134.             DrawScroll (MenuRect, topScroll);
  135.             MenuClip.top += scrlIconHeight;
  136.             }
  137.         if (TotMenuRect.bottom != MenuRect->bottom)
  138.             {
  139.             DrawScroll (MenuRect, botScroll);
  140.             MenuClip.bottom -= scrlIconHeight;
  141.             }
  142.         SaveClip = NewRgn ();
  143.         GetClip (SaveClip);
  144.         ClipRect (&MenuClip);
  145.         }
  146.     HLock ((Handle) TheMenu);
  147.     ItemString = (Str255 *) (**TheMenu).menuData;
  148.     ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
  149.     ItemRect = TotMenuRect;
  150.     ItemRect.bottom = ItemRect.top;
  151.     while ((*ItemString) [0] != (char) 0) //#C#
  152.         {
  153.         ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
  154.         ItemRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
  155.         if (ItemRect.bottom > MenuClip.top && ItemRect.top < MenuClip.bottom)
  156.             DrawItem (*ItemString, ItemInfo, &ItemRect, (short) (EnableFlags &
  157.                     1));
  158.         ItemString = (Str255 *) (ItemInfo + 1);
  159.         ItemRect.top = ItemRect.bottom;
  160.         EnableFlags >>= 1;
  161.         }
  162.     HUnlock ((Handle) TheMenu);
  163.     if (SaveClip != (RgnHandle) null)
  164.         {
  165.         SetClip (SaveClip);
  166.         DisposeRgn (SaveClip);
  167.         }
  168.     sgAtMenuBottom = TotMenuRect.bottom; //#D#
  169.     *((short *) ((*sgMBSaveLoc) + 16)) = 1;
  170.     }
  171.  
  172.  
  173. #pragma segment Main
  174. /******************************************************************************\
  175. * DrawItem - Draw a menu item
  176. *
  177. * DrawItem draws a menu item whose text is specified by ItemString and whose
  178. * item information is specified by ItemData.  The rectangle that the item
  179. * occupies on the screen is specified by ItemRect.  If the item is enabled,
  180. * Enabled must be true, otherwise it must be false.  DrawItem also draws mark
  181. * characters (like check marks); big, scaled, and disabled icons, dims items if
  182. * they're not enabled, and draws gray lines if the item string begins with a
  183. * hyphen.  Any command key characters that aren't printable are ignored.  If the
  184. * specified item icon can't be found, it is not drawn (of course), but space is
  185. * left for it.
  186. *
  187. * Coding Notes:
  188. * #A# - This calculation figures out the proper vertical coordinate to begin
  189. *       drawing the item string so that it's centered vertically in ItemRect.
  190. * #B# - Draw the mark character unless this is a hierarchical menu item.
  191. * #C# - Draw the command-key equivalent
  192. * #E# - Draw the item icon
  193. * #F# - With these command-key equivalents, icons are half their size.
  194. * #G# - If couldn't load icon, ignore drawing and continue
  195. * #H# - With this command-key equivalent, icon is dimmed.
  196. * #I# - These values will be used to set the location of the item string.
  197. \******************************************************************************/
  198.  
  199. void
  200. DrawItem (Str255 ItemString,ItemInfoPtr ItemData,Rect* ItemRect,short Enabled)
  201. {
  202.     short        HorzPos;   //Horizontal position to draw item
  203.     short        VertPos;   //Vertical position to draw item
  204.     short        MarkWidth; //Width of item mark
  205.     Handle       ItemIcon;  //=> Item's icon
  206.     Rect         IconRect;  //Rectangle of icon
  207.     short        IconSize;  //Size of icon in pixels
  208.     FontInfo     CurrFont;  //Current font's characteristics
  209.     PenState     CurrPen;   //Current characteristics of graphics pen
  210.     short        CurrFile;  //Refnum of current resource file
  211.     SICNData     **SICNRes; //=> SICN resource
  212.     TextStateRec TextState; //Current characteristics of text drawing
  213.  
  214.     GetPenState (&CurrPen);
  215.     if (ItemString [1] == '-')
  216.         {
  217.         PenSize (1, 1);
  218.         PenMode (patOr);
  219.         PenPat (&qd.gray);
  220.         MoveTo (ItemRect->left, ItemRect->top + ItemRect->bottom >> 1);
  221.         Line (ItemRect->right - ItemRect->left, 0);
  222.         }
  223.     else
  224.         {
  225.         PenMode (patOr);
  226.         GetTextState (&TextState);
  227.         TextFace (normal);
  228.         TextMode (srcOr);
  229.         GetFontInfo (&CurrFont);
  230.         MarkWidth = CurrFont.widMax;
  231.         if (ItemData->markChar != '\0' || ItemData->kbdEquiv != '\0')
  232.             {
  233.             VertPos = ((short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
  234.                     ascent + CurrFont.descent + CurrFont.leading) >> 1) +
  235.                     CurrFont.ascent + ItemRect->top); //#A#
  236.             if (ItemData->markChar != (char) 0 && ItemData->kbdEquiv !=
  237.                     hMenuCmd) //#B#
  238.                 {
  239.                 HorzPos = ItemRect->left + itemHorzMarg;
  240.                 MoveTo (HorzPos, VertPos);
  241.                 DrawChar (ItemData->markChar);
  242.                 }
  243.             if (ItemData->kbdEquiv > '!') //#C#
  244.                 {
  245.                 HorzPos = ItemRect->right - itemHorzMarg -
  246.                         CurrFont.widMax - CharWidth (cmmdCharCode);
  247.                 MoveTo (HorzPos, VertPos);
  248.                 DrawChar (cmmdCharCode);
  249.                 DrawChar (ItemData->kbdEquiv);
  250.                 }
  251.             else if (ItemData->kbdEquiv == hMenuCmd)
  252.                 {
  253.                 HorzPos = ItemRect->right - sicnSize;
  254.                 VertPos = (short) ((ItemRect->bottom - ItemRect->top - (short)
  255.                         sicnSize) >> 1) + ItemRect->top;
  256.                 CurrFile = CurResFile ();
  257.                 UseResFile (0);
  258.                 if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID))
  259.                         != (SICNData **) null)
  260.                     DrawSICN (SICNRes, heirArrow, HorzPos, VertPos);
  261.                 UseResFile (CurrFile);
  262.                 }
  263.             }
  264.         if (ItemData->iconNum != (Byte) 0) //#E#
  265.             {
  266.             IconSize = iconSize;
  267.             if (ItemData->kbdEquiv == (char) 0x1D || ItemData->kbdEquiv ==
  268.                     (char) 0x1F) //#F#
  269.                 IconSize >>= 1;
  270.             if ((ItemIcon = GetIcon (ItemData->iconNum + 256)) != (Handle) null) //#G#
  271.                 {
  272.                 IconRect.top = (ItemRect->bottom - ItemRect->top -
  273.                         IconSize >> 1) + ItemRect->top;
  274.                 IconRect.left = ItemRect->left + itemHorzMarg + MarkWidth +
  275.                         markItemGap;
  276.                 IconRect.bottom = IconRect.top + IconSize;
  277.                 IconRect.right = IconRect.left + IconSize;
  278.                 DrawICON (ItemIcon, &IconRect);
  279.                 if (ItemData->kbdEquiv == (char) 0x1F) //#H#
  280.                     DimRect (&IconRect);
  281.                 }
  282.             IconSize += iconItemGap; //#I#
  283.             }
  284.         else
  285.             IconSize = 0; //#I#
  286.         TextFace (ItemData->charStyle);
  287.         GetFontInfo (&CurrFont);
  288.         VertPos = (short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
  289.                 ascent + CurrFont.descent + CurrFont.leading) >> 1) + CurrFont.
  290.                 ascent + ItemRect->top;
  291.         HorzPos = ItemRect->left + itemHorzMarg + MarkWidth + markItemGap +
  292.                 IconSize;
  293.         MoveTo (HorzPos, VertPos);
  294.         DrawString (ItemString);
  295.         SetTextState (&TextState);
  296.         if (! Enabled)
  297.             DimRect (ItemRect);
  298.         }
  299.     SetPenState (&CurrPen);
  300.     }
  301.  
  302.  
  303. #pragma segment Main
  304. /******************************************************************************\
  305. * DimRect - Dim a rectangle
  306. *
  307. * DimRect dims the rectangle specified by ItemRect by bit-clearing it with a
  308. * medium gray pattern.  Normally, we could do this just by drawing over the item
  309. * with the standard gray pattern, but there's a problem: what if the menu has
  310. * scrolled an odd number of pixels and we have to draw part of a dimmed menu
  311. * item?  We'll end up with the gray pattern that's out of phase with the part of
  312. * the menu item that was already drawn.  To solve this, DimRect creates its own
  313. * pattern "on the fly" in GrayPat.  Two gray patterns can be created, each one
  314. * being out of out of phase with the other by one pixel.  The particular pattern
  315. * is chosen by checking to see whether the system global, TopMenuItem, is odd or
  316. * even.  The current pen state is unchanged.
  317. \******************************************************************************/
  318.  
  319. static void
  320. DimRect (TheRect)
  321.     Rect *TheRect; //-> Rectangle to dim >>
  322.     {
  323.     PenState CurrPen;     //Current characteristics of graphics pen
  324.     short    PatElem;     //Pattern element
  325.     short    GrayPat [4]; //Gray pattern (not 8 bytes 'cause it's easier here
  326.     short    PatInd;      //Index into pattern array
  327.  
  328.     GetPenState (&CurrPen);
  329.     PenMode (patBic);
  330.     if ((sgTopMenuItem & 0x0001) == 0)
  331.         PatElem = (short) 0xAA55;
  332.     else
  333.         PatElem = (short) 0x55AA;
  334.     for (PatInd = 0; PatInd < 4; PatInd++)
  335.         GrayPat [PatInd] = PatElem;
  336.     PenPat ((Pattern*) GrayPat);
  337.     PaintRect (TheRect);
  338.     SetPenState (&CurrPen);
  339.     }
  340.  
  341.  
  342. #pragma segment Main
  343. /******************************************************************************\
  344. * DrawScroll - Draw a scroll arrow
  345. *
  346. * DrawScroll draws a top scroll arrow if Which is topScroll, and it draws a
  347. * bottom scroll arrow if which is botScroll.  The menu's rectangle must be
  348. * specified in MenuRect.
  349. \******************************************************************************/
  350.  
  351. void
  352. DrawScroll (Rect* MenuRect,short Which)
  353. {
  354.     SICNData **SICNRes; //=> SICN resource
  355.     short    HorzPos;   //Horizontal position of icon
  356.     short    VertPos;   //Vertical position of icon
  357.     Rect     ScrlRect;  //Rectangle of scroll icon area
  358.     PenState CurrPen;   //Current pen state
  359.     short    CurrFile;  //Current resource file's refnum
  360.  
  361.     HorzPos = (short) ((MenuRect->right - MenuRect->left - sicnSize) >> 1) +
  362.             MenuRect->left;
  363.     ScrlRect = *MenuRect;
  364.     GetPenState (&CurrPen);
  365.     PenPat (&qd.black);
  366.     PenMode (patCopy);
  367.     PenSize (1, 1);
  368.     if (Which == topScroll)
  369.         {
  370.         ScrlRect.bottom = ScrlRect.top + scrlIconHeight;
  371.         EraseRect (&ScrlRect);
  372.         MoveTo (MenuRect->left, MenuRect->top + scrlIconHeight - 1);
  373.         Line (MenuRect->right - MenuRect->left, 0);
  374.         VertPos = MenuRect->top + 1;
  375.         }
  376.     else
  377.         {
  378.         ScrlRect.top = ScrlRect.bottom - scrlIconHeight;
  379.         EraseRect (&ScrlRect);
  380.         MoveTo (MenuRect->left, MenuRect->bottom - scrlIconHeight);
  381.         Line (MenuRect->right - MenuRect->left, 0);
  382.         VertPos = MenuRect->bottom - 1 - sicnSize;
  383.         }
  384.     PenMode (patOr);
  385.     CurrFile = CurResFile ();
  386.     UseResFile (0);
  387.     if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID)) !=
  388.             (SICNData **) null)
  389.         DrawSICN (SICNRes, Which, HorzPos, VertPos);
  390.     UseResFile (CurrFile);
  391.     SetPenState (&CurrPen);
  392.     }
  393.  
  394.  
  395. #pragma segment Main
  396. /******************************************************************************\
  397. * DrawSICN - Draw a small icon
  398. *
  399. * DrawSICN draws the small icon specified by TheIcon into the current port.
  400. * Each SICNData can hold any number of SICNs, so Index specifies which SICN to
  401. * draw, 0 specifying the first.  HorzPos and VertPos specify the horizontal and
  402. * vertical position to draw the top-left corner of the icon in local
  403. * coordinates.  If TheIcon doesn't specify a SICN or if Index is out of range,
  404. * garbage will be drawn.  The transfer mode will be the equivalent of the
  405. * current pen mode of the current port.  For example, if the current pen mode is
  406. * patXor, the SICN will be drawn in srcXor mode.
  407. \******************************************************************************/
  408.  
  409. static void
  410. DrawSICN (SICNData** TheIcon,short Index,short HorzPos,short VertPos)
  411. {
  412.     BitMap  IconBits;  //Bitmap for icon
  413.     GrafPtr CurrPort;  //-> Current GrafPort
  414.     Rect    SICNRect;  //Rectangle to draw icon into
  415.     short   TransMode; //Transfer mode to use
  416.  
  417.     HLock ((Handle) TheIcon);
  418.     SetRect (&IconBits.bounds, 0, 0, sicnSize, sicnSize);
  419.     IconBits.rowBytes = 2;
  420.     IconBits.baseAddr = (Ptr) (*TheIcon + Index);
  421.     SetRect (&SICNRect, HorzPos, VertPos, HorzPos + sicnSize, VertPos +
  422.             sicnSize);
  423.     GetPort (&CurrPort);
  424.     if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
  425.         TransMode = srcCopy;
  426.     else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
  427.         TransMode = srcOr;
  428.     else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
  429.         TransMode = srcXor;
  430.     else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
  431.         TransMode = srcBic;
  432.     CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, &SICNRect,
  433.             TransMode, (RgnHandle) null);
  434.     HUnlock ((Handle) TheIcon);
  435.     }
  436.  
  437.  
  438. #pragma segment Main
  439. /******************************************************************************\
  440. * DrawICON - Draw an icon
  441. *
  442. * DrawICON draws the icon specified by TheIcon into the current port.  IconRect
  443. * specifies the size and location to draw the icon in local coordinates.  If
  444. * TheIcon doesn't specify an ICON, garbage will be drawn.  The transfer mode
  445. * will be the equivalent of the current pen mode of the current port.  For
  446. * example, if the current pen mode is patXor, the ICON will be drawn in srcXor
  447. * mode.
  448. \******************************************************************************/
  449.  
  450. static void
  451. DrawICON (TheIcon, IconRect)
  452.     Handle TheIcon; //=> Icon data >>
  453.     Rect   *IconRect; //-> Rectangle to draw icon into >>
  454.     {
  455.     BitMap  IconBits;  //Bitmap for icon
  456.     GrafPtr CurrPort;  //-> Current GrafPort
  457.     short   TransMode; //Transfer mode to use
  458.  
  459.     HLock (TheIcon);
  460.     SetRect (&IconBits.bounds, 0, 0, iconSize, iconSize);
  461.     IconBits.rowBytes = 4;
  462.     IconBits.baseAddr = *TheIcon;
  463.     GetPort (&CurrPort);
  464.     if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
  465.         TransMode = srcCopy;
  466.     else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
  467.         TransMode = srcOr;
  468.     else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
  469.         TransMode = srcXor;
  470.     else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
  471.         TransMode = srcBic;
  472.     CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, IconRect,
  473.             TransMode, (RgnHandle) null);
  474.     HUnlock (TheIcon);
  475.     }
  476.